<template>
  <div>
    <el-upload
      v-bind="config"
      :accept="uploadAccept"
      :before-upload="handleBeforeUpload"
      :class="{hide: !disableUpload}"
      :multiple="multiple"
      :listType="listType"
      :file-list="fileList"
      :on-preview="handleDownFile"
      :on-remove="handleRemoveFile"
      :on-success="handleSuccess"
      :on-exceed="handleExceed"
      ref="upload"
      :limit="uploadLimit">
      <slot v-if="disableUpload"></slot>
      <div slot="file" v-if="listType !== 'text'" slot-scope="{file}" class="el-upload-list__item is-ready">
        <el-progress
          v-if="file.status === 'uploading'"
          :type="listType === 'picture-card' ? 'circle' : 'line'"
          :stroke-width="listType === 'picture-card' ? 6 : 2"
          :percentage="parsePercentage(file.percentage)">
        </el-progress>
        <img
          class="el-upload-list__item-thumbnail"
          :src="file.url"
        >
        <span class="el-upload-list__item-actions">
          <span
            class="el-upload-list__item-preview"
            @click="handlePictureCardPreview(file)"
          >
            <i class="el-icon-zoom-in"></i>
          </span>
          <span
            v-permission="['file:downFile']"
            class="el-upload-list__item-delete"
            @click="handleDownFile(file)"
          >
            <i class="el-icon-download"></i>
          </span>
          <span
            class="el-upload-list__item-delete"
            @click="handleRemoveFile(file, $refs.upload.uploadFiles)"
          >
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </div>
    </el-upload>
    <ms-dialog center-scroll :tools="false" :title="dialogName" :dialog-visible="dialogVisible" @close="dialogVisible = false">
      <img width="100%" :src="dialogImageUrl">
    </ms-dialog>
  </div>
</template>

<script>
import MsDialog from '@/common/dialog'
import { downFile } from '@/utils/axios'
import { getToken } from '@/utils/token'
const accept = 'image/png,image/jpg,image/jpeg'
const BASE_API = process.env.VUE_APP_BASE_API
const FILE_UNIT = ['KB', 'MB', 'GB']
export default {
  components: {
    MsDialog
  },
  props: {
    multiple: {
      type: Boolean,
      default: false
    },
    limit: {
      type: Number
    },
    listType: {
      type: String,
      default: 'text'
    },
    filePath: {
      type: String,
      required: true
    },
    processId: {
      type: String
    },
    fileSize: {
      type: Number
    },
    sizeUnit: {
      type: String,
      default: 'KB',
      validator: (val) => {
        return FILE_UNIT.indexOf(val) !== -1
      }
    }
  },
  data() {
    return {
      config: {
        headers: {
          Authorization: getToken()
        },
        data: {
          editorType: 0,
          filePath: this.filePath,
          fileType: this.listType !== 'text' ? 1 : 0,
          processId: this.processId
        },
        action: BASE_API + 'sys/file/upload'
      },
      succFileList: [],
      disableUpload: true,
      dialogImageUrl: '',
      dialogVisible: false,
      dialogName: '放大',
      removeIds: [],
      fileList: []
    }
  },
  computed: {
    // 上传数量
    uploadLimit() {
      return this.multiple ? this.limit : 1
    },
    // 上传格式
    uploadAccept() {
      return this.listType !== 'text' ? accept : ''
    }
  },
  methods: {
    // 校验文件大小
    handleSizeValid(size, validType) {
      let baseSize = size / 1024
      if (validType === 1) {
        baseSize = baseSize / 1024
      } else if (validType === 2) {
        baseSize = baseSize / 1024 / 1024
      }
      return baseSize < this.fileSize
    },
    handleBeforeUpload(file) {
      const h = this.$createElement
      const fileSize = this.fileSize
      const sizeUnit = this.sizeUnit
      if (fileSize && sizeUnit) {
        const isOverFlag = this.handleSizeValid(file.size, FILE_UNIT.indexOf(sizeUnit))
        if (!isOverFlag) {
          this.$message.error(`文件大小超过 ${fileSize}${sizeUnit}`)
          return false
        }
      }
      // 处理文件格式
      if (this.listType !== 'text') {
        if (!accept.split(',').includes(file.type)) {
          this.$message({
            message: h('p', { class: 'el-message__content' }, [
              h('p', { class: 'el-message__content' }, '上传图片格式不正确'),
              h('p', { class: 'el-message__content' }, `请上传${accept}格式文件`)
            ]),
            type: 'error'
          })
          return false
        }
      }
    },
    handleSuccess(xhr, file, fileList) {
      let id = xhr.obj.fileId
      this.fileList.push(file)
      this.succFileList.push(id)
      this.handleDisableUpload(fileList)
    },
    patchList(fileList) {
      const newFileList = fileList.filter((file) => this.isUploads(file))
        .map((file) => file.response.obj)
      const fileConf = {
        newFileList,
        removeIds: this.removeIds
      }
      this.$emit('fileList', fileConf)
    },
    // 是否显示上传按钮
    handleDisableUpload(fileList = []) {
      if (this.uploadLimit <= this.fileList.length) {
        this.disableUpload = false
      } else {
        this.disableUpload = true
      }
      this.patchList(fileList)
    },
    handleSetUploadFile(list) {
      // 清空数据
      this.fileList = list.length === 0 ? [] : list
      this.handleDisableUpload()
    },
    // 查看大图
    handlePictureCardPreview(file) {
      const { name, url } = file
      this.dialogImageUrl = url
      this.dialogName = name
      this.dialogVisible = true
    },
    handleRemoveFile(file, fileList) {
      // 文件是否已经上传至服务器上
      if (!(this.isUploads(file))) {
        this.removeIds.push(file.fileId)
      }
      const existFileList = this.fileList.indexOf(file)
      // fix beforeUpload
      if (existFileList !== -1) {
        this.fileList.splice(this.fileList.indexOf(file), 1)
        this.handleDisableUpload(fileList)
      }
    },
    // 上传选择限制
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 ${this.uploadLimit} 个文件，本次选择了 ${files.length} 个文件，只可选择 ${this.uploadLimit - fileList.length} 个文件`)
    },
    handleClearFileList() {
      this.$refs['upload'].clearFiles()
      this.disableUpload = true
      this.fileList = this.succFileList = []
    },
    handleSetFileList(list) {
      const newList = this._.cloneDeep(list)
      const fileList = newList.map(element => {
        if (element.base64) {
          element.url = element.base64
        } else {
          element.url = BASE_API + 'upload/' + element.url
        }
        return element
      })
      this.fileList = fileList
      this.handleDisableUpload()
    },
    handleDownFile(file) {
      const fileId = this.isUploads(file) ? file.response.obj.fileId : file.fileId
      downFile(fileId)
    },
    // 文件是否已保存表单
    isUploads(file) {
      return file.hasOwnProperty('response')
    },
    parsePercentage(val) {
      return parseInt(val, 10)
    }
  }
}
</script>

<style lang="stylus">
  .hide
    .el-upload--text
      display none
    .el-upload--picture-card
      display none
  .el-upload-list__item
    .is-ready
      border-left-width 0px
      border-top-width 0px
    .el-progress--circle
      background radial-gradient(black, transparent)
</style>
